﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace SuperKit
{


    public class ImageCompare : CommandExecutor {
        public float SameRate { get; }
        public int ColorDiff { get; }
        public float KeepRate { get; }
        public int MinKeepCount { get; }
        public int MaxKeepCount { get; }
        public DirectoryInfo DirInfo { get; private set; }
        public List<ImageGroup> Groups { get; private set; }
        private double lastRefresh = 0;
        public int SkipCount { get; }

        public ImageCompare(ArgReader arg, IExecutorOwner form, string fpath) : base(arg, form, fpath) {
            SameRate = arg.GetFloat("-SameRate", 0.9f);
            ColorDiff = arg.GetInteger("-ColorDiff", ImageGroupItem.DEFAULT_COLOR_DIFF);
            MinKeepCount = arg.GetInteger("-MinKeepCount", 0);
            MaxKeepCount = arg.GetInteger("-MaxKeepCount", 0);
            KeepRate = arg.GetFloat("-KeepRate", 0.5f);
            SkipCount = arg.GetInteger("-SkipCount", 0);
            if (Kit.IsEmpty(TargetDir)) {
                TargetDir = "(Same)";
            }
        }

        public override void Execute() {
            DirInfo = new DirectoryInfo(FilePath);
            List<FileGroup> groups = new List<FileGroup>();
            FileGroup.GetAllFileGroup(DirInfo, groups);
            Groups = new List<ImageGroup>();

            foreach (var group in groups) {
                if (group.IsEmpty) {
                    continue;
                }
                
                ImageGroup img = new ImageGroup(this, group);

                if (img.IsEmpty || img.Count <= GetKeepCount(img)) {
                    continue;
                }

                if (SkipCount != 0 && img.Count > SkipCount) {
                    Flush("跳过{0}，因为数量大于{1}({2})", img.Name, SkipCount, img.Count);
                }

                Groups.Add(img);
            }

            Thread t = new Thread(OnProcess);
            t.Start();
        }

        private void OnProcess() {
            while (GetLeft() > 0) {
                StartCompare();
                PrintStatus();
                Thread.Sleep(100);
            }

            PrintStatus();
            PrintAll();

            End();
        }

        private void CountDeleted() {
            foreach (var i in Groups) {
                if (i.Status != ThreadStatus.COMPLETE) {
                    continue;
                }
            }
        }

        private void PrintStatus() {
            var current = Kit.SecondsTick;
            if (current > (lastRefresh + 0.1f)) {
                SetTitle($"运行:{GetRuuning()}, 完成:{GetComplete()}/{Groups.Count}");
                lastRefresh = current;
            }            
        }

        private void StartCompare() {
            int running = GetRuuning();
            if (running >= MaxThread) {
                return;
            }
            foreach (var i in Groups) {
                if (i.Status == ThreadStatus.READY) {
                    i.Start();
                    return;
                }
            }
        }

        private int GetRuuning() {
            int count = 0;
            foreach (var i in Groups) {
                if (i.Status == ThreadStatus.PROCESS) {
                    count++;
                }
            }
            return count;
        }

        private int GetLeft() {
            int count = 0;
            foreach (var i in Groups) {
                if (i.Status != ThreadStatus.COMPLETE) {
                    count++;
                }
            }
            return count;
        }

        private int GetComplete() {
            int count = 0;
            foreach (var i in Groups) {
                if (i.Status == ThreadStatus.COMPLETE) {
                    count++;
                }
            }
            return count;
        }

        public int GetKeepCount(ImageGroup img) {
            int keep = (int)(Math.Ceiling(KeepRate * img.Count));
            if (MinKeepCount != 0 && keep < MinKeepCount) {
                keep = MinKeepCount;
            }
            if (MaxKeepCount != 0 && keep > MaxKeepCount) {
                keep = MaxKeepCount; 
            }
            return keep;
        }

        public void PrintAll() {
            float saveMB = 0f;
            float totalMB = 0f;
            int saveCount = 0;
            int totalCount = 0;
            foreach (var i in Groups) {
                i.CalculateCount();
                saveMB += i.SaveMB;
                totalMB += i.TotalMB;
                saveCount += i.SaveCount;
                totalCount += i.Count;
            }

            Flush("总计：保留文件（{0}/{1}），保留MB（{2:N1}/{3:N1}）", saveCount, totalCount, saveMB, totalMB);
        }

        public void Print(ImageGroup img) {
            img.CalculateCount();

            Flush("{0}({1}文件[{2:N1}MB])(保留{3}文件[{4:N1}MB,{5:N0}%])", img.Name, img.Count, img.TotalMB,
                img.SaveCount, img.SaveMB, img.SaveMB / img.TotalMB * 100.0f);            
        }




        public void Move(ImageGroup img) {
            foreach (var i in img.Items) {
                if (!i.Enable) {
                    //Flush("删除：{0}(相似:{1})", i.Info.Name, i.SameCount);
                    MoveToTagetDir(i.Info);
                }
            }
        }

        public void MoveToTagetDir(FileInfo i) {
            var targetPath = CreateTargetDir();
            var newDir = CalculateNewDir(DirInfo.FullName, targetPath, i.Directory.FullName);
            if (!Directory.Exists(newDir)) {
                Directory.CreateDirectory(newDir);
            }
            var newPath = Path.Combine(newDir, i.Name);
            if (File.Exists(newPath)) {
                Flush("目标文件已经存在：{0}", newPath);
                return;
            }
            if (IsTest == false) {
                File.Move(i.FullName, newPath);
                SetStatus("MoveTo: {0}", newPath);
            }
        }

    }
}
